package cn.com.se.多线程.ThreadPoolExecutorTest.ThreadExPool;

import java.util.Locale;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolExecutorTest {
    /**
     * 定义队列
     */
    private static BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(5);

    /**
     * 参数介绍：
     *      核心线程数大小：3
     *      最大线程池大小：5
     *      当线程没有任务时最多保留时间：300(单位可以配置)
     *      自定义线程工厂：实现ThreadFactory接口
     *      阻塞队列
     * 队列分类：
     *      ArrayBlockingQueue ：有界的数组队列，先进先出，此队列创建时必须指定大小
     *      SynchronousQueue :  同步的阻塞队列，它不会保存提交的任务，而是将直接新建一个线程来执行新来的任务
     *      LinkedBlockingQueue ：基于链表的先进先出队列，可支持有界/无界的队列，如果创建时没有指定此队列大小，则默认为Integer.MAX_VALUE
     *      PriorityBlockingQueue ：优先队列，可以针对任务排序
     * 线程工厂：
     *      自定义线程工厂实现ThreadFactory接口,可以实现创建自定义线程
     * 拒绝策略：
     *      new ThreadPoolExecutor.AbortPolicy : 直接丢弃后来的任务并抛出RejectedExecutionException异常。
     *      new ThreadPoolExecutor.DiscardPolicy ：直接丢弃后来的任务，但是不抛出异常。
     *      new ThreadPoolExecutor.DiscardOldestPolicy ：丢弃队列最前面的任务，然后重新尝试执行任务（重复此过程）
     *      new ThreadPoolExecutor.CallerRunsPolicy ：直接调用 run 方法并且阻塞执行
     * 说明:
     *      1、当线程池中任务小于核心线程数(corePoolSize)时，线程池将创建一个新的线程来执行任务，即使线程池中存在空闲线程
     *      2、当线程池中任务数达到核心线程数(corePoolSize)时，新任务将会被放到queue中等待线程池的调度
     *      3、当队列已满并且线程池最大线程数(maximumPoolSize)大于核心线程数(corePoolSize)时新任务会创建新的线程执行
     *      4、当任务数大于线程池最大线程数(maximumPoolSize)+队列容量时将会执行TestHanlder(自定义)内容,也可以使用默认的策略
     *      5、当线程池中线程数超过核心线程数(corePoolSize)线程并且有线程空闲时间达到活跃时间(keepAliveTime)时,关闭空闲线程
     */
    public static  ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 300L, TimeUnit.HOURS, queue,new TestFactory(), new TestHandler());

    /**
     * 自定义拒绝策略
     */
    private static class TestHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            System.out.println("线程池已经满了....");
        }
    }

    /**
     * 自定义线程工厂
     */
    private static class TestFactory implements ThreadFactory {
        private final AtomicInteger atomic = new AtomicInteger(1);
        /**
         * 创建自定义线程
         * @param r
         * @return
         */
        @Override
        public Thread newThread(Runnable r) {
            // 自定义线程名称
            Thread thread=  new Thread(r,String.format(Locale.CHINA,"%s%d","老哥群的同志们好",atomic.getAndIncrement()));
            // 是否是守护线程(当主线程结束时子线程一起结束)
            // thread.setDaemon(true);
            return thread;
        }
    }

    /**
     * 测试入口
     * @param args
     */
    public static void main(String[] args) {
        for (int i = 0; i < 11; i++) {
            threadPoolExecutor.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程：" + Thread.currentThread().getName());
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}
